package com.water.wfo.component.redis;

import com.alibaba.fastjson.JSON;
import com.water.wfo.component.constant.enums.CacheKeyEnum;
import com.water.wfo.component.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * packageName com.water.wfo.component.redis
 *
 * @author
 * @className WfoRedisService(处以class为网)
 * @date 2025/3/13
 * @description T0D0
 */
@Slf4j
public class WfoRedisService {

    protected StringRedisTemplate redisTemplate;

    public WfoRedisService(StringRedisTemplate redisTemplate){
        this.redisTemplate = redisTemplate;
    }

    protected <T> String parseValue(T value) {
        String valueTmp;
        if (value instanceof String) {
            valueTmp = (String)value;
        } else {
            valueTmp = JSON.toJSONString(value);
        }

        return valueTmp;
    }
    public void delete(String key) {
        if(null == key){
            return;
        }
        try {
            redisTemplate.delete(key);
        } catch (Exception e) {
            log.error("redis delete error", e);
        }
    }


    /**
     * 存入缓存
     * @param cacheKeyEnum
     * @param value
     */
    public <T> void set(CacheKeyEnum cacheKeyEnum, T value, String... vars){
        if(null == cacheKeyEnum || null == value){
            return;
        }
        try {
            String cacheValue = this.parseValue(value);
            String key = cacheKeyEnum.desKey(vars);
            if(cacheKeyEnum.getTimeout()>0) {
                redisTemplate.opsForValue().set(key, cacheValue, cacheKeyEnum.getTimeout(), TimeUnit.SECONDS);
            }else{
                redisTemplate.opsForValue().set(key, cacheValue);
            }
        } catch (Exception e){
            log.error("redis set error", e);
        }
    }


    /**
     * 存入缓存(如果不存在，则设置)
     * @param key
     * @param value
     * @param time
     * @param <T>
     */
    public <T> boolean setnx(String key, T value, long time) {
        if (null != key && null != value && time != 0L) {
            try {
                return this.redisTemplate.opsForValue().setIfAbsent(key, this.parseValue(value), time, TimeUnit.SECONDS);
            } catch (Exception var6) {
                log.error("redis set time error", var6);
                return false;
            }
        }
        return false;
    }

    /**
     * 获取 String 类型 key-value，如果value为空，但CacheKeyEnum中配置默认值不为空，则返回该默认值
     * @param cacheKeyEnum
     * @return
     */
    public String get(CacheKeyEnum cacheKeyEnum, String... vars){
        String value = this.get(cacheKeyEnum.desKey(vars));
        if(StringUtil.isBlank(value) && StringUtil.isNotBlank(cacheKeyEnum.getDefaultValue())){
            value = cacheKeyEnum.getDefaultValue();
        }
        return value;
    }
    /**
     * @Description
     * * @param key
     * @Return java.lang.String
     * @Date 2025/3/14 10:02
     *
     */
    public String get(String key) {
        if (null == key) {
            return null;
        } else {
            try {
                return (String)this.redisTemplate.opsForValue().get(key);
            } catch (Exception var3) {
                log.error("redis get error", var3);
                return null;
            }
        }
    }

    /**
     * 获取缓存对象
     * @param cacheKeyEnum  缓存枚举
     * @param clazz         解析对象
     * @param vars          key变量
     * @param <T>
     * @return
     */
    public <T> T getObject(CacheKeyEnum cacheKeyEnum, Class<T> clazz, String... vars) {
        if (null == cacheKeyEnum) {
            return null;
        } else {
            try {
                String value = this.get(cacheKeyEnum.getKey());
                return StringUtil.isBlank(value) ? null : JSON.parseObject(value, clazz);
            } catch (Exception var4) {
                log.error("redis getObject error", var4);
                return null;
            }
        }
    }

    /**
     * 获取缓存列表
     * @param cacheKeyEnum  缓存枚举
     * @param clazz         解析对象
     * @param vars          key变量
     * @param <T>
     * @return
     */
    public <T> List<T> getObjectArray(CacheKeyEnum cacheKeyEnum, Class<T> clazz, String... vars) {
        if (null == cacheKeyEnum) {
            return null;
        } else {
            try {
                String value = this.get(cacheKeyEnum.getKey());
                return StringUtil.isBlank(value) ? null : JSON.parseArray(value, clazz);
            } catch (Exception var4) {
                log.error("redis getObjectArray error", var4);
                return null;
            }
        }
    }

    /**
     * 添加元素,有序集合是按照元素的score值由小到大排列
     * @param cacheKeyEnum
     * @param value
     * @param score
     * @return
     */
    public Boolean zAdd(CacheKeyEnum cacheKeyEnum, String value, double score, String... vars) {
        String key = cacheKeyEnum.desKey(vars);
        return redisTemplate.opsForZSet().add(key, value, score);
    }

    /**
     * 设置过期时间
     * @param cacheKeyEnum
     * @param timeout
     * @param unit
     * @return
     */
    public boolean expire(CacheKeyEnum cacheKeyEnum, long timeout, TimeUnit unit, String... vars) {
        String key = cacheKeyEnum.desKey(vars);
        return redisTemplate.expire(key, timeout, unit);
    }

    public boolean expire(String key, long time, TimeUnit type) {
        if (null == key) {
            return false;
        } else {
            try {
                return this.redisTemplate.boundValueOps(key).expire(time, type);
            } catch (Exception var6) {
                log.error("redis expire error", var6);
                return false;
            }
        }
    }

    /**
     * 根据索引值移除区间元素
     * @param cacheKeyEnum
     * @param start
     * @param end
     * @return
     */
    public Long removeRangeByScore(CacheKeyEnum cacheKeyEnum, long start, long end, String... vars) {
        String key = cacheKeyEnum.desKey(vars);
        return redisTemplate.opsForZSet().removeRangeByScore(key,start,end);
    }

    /**
     * 返回有序集合，一段范围的数据
     * @param cacheKeyEnum       缓存key
     * @param start     开始下标
     * @param end       结束下标
     * @return          集合
     */
    public Set<String> zrange(CacheKeyEnum cacheKeyEnum, long start, long end, String... vars){
        Set<String> result = null;
        String key = cacheKeyEnum.desKey(vars);
        try{
            result = redisTemplate.opsForZSet().range(key, start, end);
        }catch (Exception e) {
            log.error("执行GwmcRedisService.zrange方法出错.", e);
        }
        return result;
    }

    /**
     * 根据索引值移除区间元素
     * @param cacheKeyEnum
     * @param start
     * @param end
     * @return
     */
    public Long removeRange(CacheKeyEnum cacheKeyEnum, long start, long end, String... vars) {
        Long result = 0L;
        String key = cacheKeyEnum.desKey(vars);
        try{
            result = redisTemplate.opsForZSet().removeRange(key,start,end);
        }catch (Exception e) {
            log.error("执行GwmcRedisService.removeRange方法出错.", e);
        }
        return result;
    }

    /**
     * 返回有序集中，成员的score
     * @param cacheKeyEnum       缓存key
     * @param member    成员
     * @return          成员的score
     */
    public Double zscore(CacheKeyEnum cacheKeyEnum, String member, String... vars){
        Double result = null;
        try{
            String key = cacheKeyEnum.desKey(vars);
            result = this.redisTemplate.opsForZSet().score(key, member);
        }catch (Exception e) {
            log.error("执行GwmcRedisService.zscore方法出错.", e);
        }
        return result;
    }

    /**
     *  对一个 key-value 的值进行减操作
     * @param key
     * @param increment
     * @param expire
     * @return
     */
    public long decrement(String key, long increment, long expire) {
        Long result = 0L;

        try {
            result = this.redisTemplate.opsForValue().decrement(key, increment);
            if (expire > 0L) {
                this.expire(key, expire,TimeUnit.SECONDS);
            }
        } catch (Exception var8) {
            log.error("执行decrement()方法出错.", var8);
        }

        return result;
    }

    /**
     * 对一个 key-value 的值进行加减操作,(超时时间每次回覆盖)
     * 如果该 key 不存在 将创建一个key 并赋值该 number
     * 如果 key 存在,但 value 不是长整型 ,将报错
     * @param key
     * @param increment
     * @param expire
     */
    public long incrementTimeout(String key,long increment,long expire, TimeUnit timeUnit){
        return this.incrementTimeout(key, increment, expire, timeUnit, Boolean.FALSE);
    }

    /**
     * 对一个 key-value 的值进行加减操作,(超时时间，初始时设置一次)
     * 如果该 key 不存在 将创建一个key 并赋值该 number
     * 如果 key 存在,但 value 不是长整型 ,将报错
     * @param key
     * @param increment
     * @param expire
     */
    public long incrementTimeoutOnce(String key,long increment,long expire, TimeUnit timeUnit){
        return this.incrementTimeout(key, increment, expire, timeUnit, Boolean.TRUE);
    }

    public Long getExpire(String key) {
        if (null == key) {
            return null;
        } else {
            try {
                return this.redisTemplate.boundValueOps(key).getExpire();
            } catch (Exception var3) {
                log.error("redis getExpire error", var3);
                return null;
            }
        }
    }

    /**
     * 对一个 key-value 的值进行加减操作,
     * 如果该 key 不存在 将创建一个key 并赋值该 number
     * 如果 key 存在,但 value 不是长整型 ,将报错
     * @param key
     * @param increment
     * @param expire
     */
    public long incrementTimeout(String key,long increment,long expire, TimeUnit timeUnit, boolean timeoutOnce){
        Long result = 0L;
        try {
            result = redisTemplate.opsForValue().increment(key, increment);
            if(expire > 0) {
                if(timeoutOnce){
                    // 单位为秒
                    long ttl = this.getExpire(key);
                    if(ttl<0){
                        this.expire(key, expire, timeUnit);
                    }
                }else{
                    this.expire(key, expire, timeUnit);
                }
            }
        } catch (Exception e) {
            log.error("执行CacheService.valueIncr()方法出错.", e);
        }
        return result;
    }

    /**
     * 获取缓存数字值
     * @param key
     * @param defaultValue
     * @return
     */
    public int getIntegerDefault(String key, int defaultValue){
        Integer value = null;
        try {
            String valueStr = this.get(key);
            if (StringUtil.isNotBlank(valueStr)) {
                value = Integer.valueOf(valueStr);
            }
        }catch (Exception e){
            log.error("getIntegerDefault error", e);
        }
        if(null == value) {
            value = defaultValue;
        }
        return value;
    }
}
